/**
 * 文件名：****.java
 * 版权：Copyright Lightkit All Rights Reserved.
 * 描述：*****
 */
package com.lightkits.wms.domain.stocktransfer.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lightkits.common.db.entity.BdTransaction;
import com.lightkits.common.db.entity.FndTransactionTypeBase;
import com.lightkits.common.db.entity.FndWmMoveTypeBase;
import com.lightkits.common.db.entity.FndWorker;
import com.lightkits.common.service.CommonTransactionService;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.object.ParseUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.framework.soa.client.id.GetGlobalIDRequestType;
import com.lightkits.framework.soa.client.id.GetGlobalIDResponseType;
import com.lightkits.framework.soa.client.id.IDServiceClient;
import com.lightkits.wms.domain.commons.service.WmsCommonsService;
import com.lightkits.wms.domain.saveonhand.models.OnhandParams;
import com.lightkits.wms.domain.saveonhand.service.UseParamsDomain;
import com.lightkits.wms.domain.stocktransfer.service.SubStockTransferDomain;
import com.lightkits.wms.dto.onhand.model.OnhandDTO;
import com.lightkits.wms.dto.stocktransfer.model.SubStockViewDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * SubStockTransferDomainImpl
 *
 * @author jing.wei@hand-china.com
 * Created on 2019/4/17 15:49
 */
@Service
public class SubStockTransferDomainImpl implements SubStockTransferDomain {
    private final WmsCommonsService wmsCommonsService;

    private final UseParamsDomain useParamsDomain;
    private final CommonTransactionService service;
    private final IDServiceClient idAdapterService;

    @Autowired
    public SubStockTransferDomainImpl(WmsCommonsService wmsCommonsService,
                                      UseParamsDomain useParamsDomain,
                                      CommonTransactionService service,
                                      IDServiceClient idAdapterService) {
        this.wmsCommonsService = wmsCommonsService;
        this.useParamsDomain = useParamsDomain;
        this.service = service;
        this.idAdapterService = idAdapterService;
    }

    /**
     * 子库存参数校验
     *
     * @param subStockViewDTO 子库存转移参数
     * @return IResult
     **/
    @Override
    public IResult checkParams(SubStockViewDTO subStockViewDTO) {
        try {
            //必输参数校验
            IntegrityValidator.begin()
                    .validate(subStockViewDTO.getEventRequestId(), "Event Request Id")
                    .validate(subStockViewDTO.getOrgId(), "Organization Id")
                    .validate(subStockViewDTO.getUomCode(), "Uom")
                    .validate(subStockViewDTO.getItemId(), "Item Id")
                    .validate(subStockViewDTO.getOutWarehouseId(), "Out Warehouse Id")
                    .validate(subStockViewDTO.getOwnerType(), "Owner Type")
                    .validate(subStockViewDTO.getInWarehouseId(), "In Warehouse Id")
                    .validate(subStockViewDTO.getMoveTypeCode(), "Move Type Code")
                    .validate(subStockViewDTO.getTransferQty(), "Transfer Quantity");
        } catch (LightKitsBizException e) {
            return e.result();
        }
        IResult result;
        //所有者校验
        result = wmsCommonsService.checkOwnerParams(subStockViewDTO.getOwnerType(),
                subStockViewDTO.getOwnerId());
        if (!result.isSuccessful()) {
            return result;
        }
        //负库存校验
        result = wmsCommonsService.checkNegativestock(subStockViewDTO.getOutWarehouseId(),
                subStockViewDTO.getOutWmAreaId(),
                subStockViewDTO.getTransferQty(),
                subStockViewDTO.getUomCode());
        return result;
    }

    /**
     * 现有量参数转换
     *
     * @param stockViewDTO 子库存参数
     * @param direaction   装换方向
     * @return OnhandDTO
     **/
    private CheckResult<OnhandDTO> convertParams(SubStockViewDTO stockViewDTO, String direaction) {
        CheckResult<OnhandDTO> checkResult = new CheckResult<>();
        checkResult.setSuccessful(true);
        OnhandDTO params = new OnhandDTO();
        if (ObjectUtil.isNullOrEmpty(direaction)) {
            checkResult.setSuccessful(false);
            checkResult.setMessage("the direction is null");
            return checkResult;
        }
        if (!direaction.equals("OUT") && !direaction.equals("IN") && !direaction.equals("ALL")) {
            checkResult.setSuccessful(false);
            checkResult.setMessage("the direction in undefiend");
            return checkResult;
        }

        params.setEventRequestId(ParseUtil.tryLongWithException(stockViewDTO.getEventRequestId()));
        params.setWorkerId(stockViewDTO.getWorkerId());
        params.setParentEventId(stockViewDTO.getParentEventId());
        params.setOrgId(stockViewDTO.getOrgId());
        params.setItemId(stockViewDTO.getItemId());
        params.setUomCode(stockViewDTO.getUomCode());
        params.setOwnerType(stockViewDTO.getOwnerType());
        params.setOwnerId(stockViewDTO.getOwnerId());
        params.setLotNumber(stockViewDTO.getLot());
        params.setRemark(stockViewDTO.getRemark());
        params.setChangeQuantity(stockViewDTO.getTransferQty());
        if (direaction.equals("OUT")) {
            params.setEventTypeCode("WM_MTL_TRANS_OUT");
            params.setWarehouseId(stockViewDTO.getOutWarehouseId());
            params.setWmAreaId(stockViewDTO.getOutWmAreaId());
            params.setChangeDirection("OUT");
        }
        if (direaction.equals("IN")) {
            params.setEventTypeCode("WM_MTL_TRANS_IN");
            params.setWarehouseId(stockViewDTO.getInWarehouseId());
            params.setWmAreaId(stockViewDTO.getInWmAreaId());
            params.setChangeDirection("IN");
        }

        checkResult.setData(params);

        return checkResult;
    }

    /**
     * @param stockViewDTO 库存转移参数
     * @param direaction   转移方向
     * @param transTypeId  事务类型ID
     * @param moveTypeId   移动类型ID
     * @return BdTransaction
     */
    private BdTransaction createTranscation(SubStockViewDTO stockViewDTO,
                                            String direaction,
                                            Long transTypeId,
                                            Long moveTypeId) {
        BdTransaction trans = new BdTransaction();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        GetGlobalIDRequestType idRequest = new GetGlobalIDRequestType();
        idRequest.setCount(1);
        GetGlobalIDResponseType idResponse = idAdapterService.getGlobalId(idRequest);
        Iterator<Long> sfIds = idResponse.getIds().iterator();
        FndTransactionTypeBase base = new FndTransactionTypeBase()
                .selectById(transTypeId);
        trans.setTransactionTypeId(transTypeId);
        trans.setTransactionTypeCode(base.getTransactionTypeCode());
        trans.setOrganizationId(ParseUtil.tryLongWithException(stockViewDTO.getOrgId()));
        trans.setId(sfIds.next());
        trans.setItemId(ParseUtil.tryLongWithException(stockViewDTO.getItemId()));
        trans.setTransactionUom(stockViewDTO.getUomCode());
        trans.setTransactionDate(new Date());
        if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getDocumentTypeId())) {
            trans.setDocumentTypeId(ParseUtil.tryLongWithException(stockViewDTO.getDocumentTypeId()));
        }
        if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getDocumentLineId())) {
            trans.setDocumentLineId(ParseUtil.tryLongWithException(stockViewDTO.getDocumentLineId()));
        }
        if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getDocumentId())) {
            trans.setDocumentId(ParseUtil.tryLongWithException(stockViewDTO.getDocumentId()));
        }
        trans.setDocumentTypeCode(stockViewDTO.getDocumentTypeCode());
        trans.setDocumentNum(stockViewDTO.getDocumentNum());
        trans.setLotNumber(stockViewDTO.getLot());
        format.applyPattern("HH:mm:ss");
        trans.setTransactionTime(new Date());
        if (direaction.equals("OUT")) {
            trans.setTransactionQty(new BigDecimal(stockViewDTO.getTransferQty()));
            trans.setWarehouseId(ParseUtil.tryLongWithException(stockViewDTO.getOutWarehouseId()));
            if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getOutWmAreaId())) {
                trans.setWmAreaId(ParseUtil.tryLongWithException(stockViewDTO.getOutWmAreaId()));
            }
        }
        if (direaction.equals("IN")) {
            trans.setTransactionQty(new BigDecimal(stockViewDTO.getTransferQty()).negate());
            trans.setWarehouseId(ParseUtil.tryLongWithException(stockViewDTO.getInWarehouseId()));
            if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getInWmAreaId())) {
                trans.setWmAreaId(ParseUtil.tryLongWithException(stockViewDTO.getInWmAreaId()));
            }
        }
        trans.setWorkerId(ParseUtil.tryLongWithException(stockViewDTO.getWorkerId()));
        trans.setEventRequestId(ParseUtil.tryLongWithException(stockViewDTO.getEventRequestId()));
        FndWorker worker = new FndWorker().selectById(stockViewDTO.getWorkerId());
        trans.setWorkerNumber(worker.getWorkerNumber());
        trans.setTransactionReasonCode(moveTypeId);
        trans.setRemark(stockViewDTO.getRemark());
        return trans;

    }

    /**
     * 子库存转移事务操作
     *
     * @param subviewDTO 库存转移参数
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult subStockTransfer(SubStockViewDTO subviewDTO) {
        if (ObjectUtil.isNullOrEmpty(subviewDTO.getEventRequestId())) {
            GetGlobalIDRequestType idRequest = new GetGlobalIDRequestType();
            idRequest.setCount(1);
            GetGlobalIDResponseType idResponse = idAdapterService.getGlobalId(idRequest);
            Iterator<Long> sfIds = idResponse.getIds().iterator();
            subviewDTO.setEventRequestId(sfIds.next().toString());
        }

        IResult result = null;
        try {
            result = this.checkParams(subviewDTO);
            if (!result.isSuccessful()) {
                return result;
            }
            CheckResult<OnhandDTO> outOnhandParams = convertParams(subviewDTO, "OUT");
            CheckResult<OnhandDTO> inOnhandParams = convertParams(subviewDTO, "IN");
            if (!outOnhandParams.isSuccessful()) {
                return IResult.fail(outOnhandParams.getMessage());
            }
            if (!inOnhandParams.isSuccessful()) {
                return IResult.fail(inOnhandParams.getMessage());
            }
            CheckResult<OnhandParams> checkResultRes = useParamsDomain.getOnhandParams(outOnhandParams.getData());
            if (!checkResultRes.isSuccessful() || checkResultRes.getData() == null) {
                throw new LightKitsBizException(checkResultRes.getMessage());
            }
            CheckResult resultOut = useParamsDomain.insertValue(checkResultRes.getData());
            if (!resultOut.isSuccessful()) {
                throw new LightKitsBizException(resultOut.getMessage());
            }
            checkResultRes = useParamsDomain.getOnhandParams(inOnhandParams.getData());
            if (!checkResultRes.isSuccessful() || checkResultRes.getData() == null) {
                throw new LightKitsBizException(checkResultRes.getMessage());
            }
            CheckResult resultIn = useParamsDomain.insertValue(checkResultRes.getData());
            if (!resultIn.isSuccessful()) {
                throw new LightKitsBizException(resultIn.getMessage());
            }
            FndWmMoveTypeBase moveTypeBase = new FndWmMoveTypeBase()
                    .selectOne(new EntityWrapper()
                            .eq(FndWmMoveTypeBase.MOVE_TYPE_CODE, subviewDTO.getMoveTypeCode()));
            if (!ObjectUtil.isEmpty(moveTypeBase.getTransactionTypeId())) {
                //create transcation
                List<BdTransaction> transactions = new ArrayList<>();
                BdTransaction positiveTrans = createTranscation(
                        subviewDTO, "OUT", moveTypeBase.getTransactionTypeId(), moveTypeBase.getId());
                BdTransaction reverseTrans = createTranscation(
                        subviewDTO, "IN", moveTypeBase.getTransactionTypeId(), moveTypeBase.getId());
                positiveTrans.setParentTransactionId(reverseTrans.getId());
                reverseTrans.setParentTransactionId(positiveTrans.getId());
                transactions.add(positiveTrans);
                transactions.add(reverseTrans);
                service.saveTransaction(transactions);
            }
        } catch (Exception e) {
            return IResult.fail("Save Onhand Quantity error");
        }
        return result;

    }


}
